package com.xihuanjun.util.tencent;

import com.fasterxml.jackson.databind.JsonNode;
import com.xihuanjun.exception.MiniAppException;
import com.xihuanjun.exception.MissingPropertiesException;
import com.xihuanjun.util.HttpUtils;
import com.xihuanjun.util.json.JSONUtils;
import com.xihuanjun.util.json.JsonResult;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: 江溪浣
 * @createDate: 2022/9/24 16:40
 * @description:
 */
@Data
@Slf4j
@ConfigurationProperties("xihuanjun.miniapp")
public class MiniAppUtils {

    private String appId=null;
    private String appSecret=null;
    private MiniAppState appState=null;

    @Getter(AccessLevel.NONE)
    @Setter(AccessLevel.NONE)
    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * 根据code获取openid，需要在配置里设置好appId和appSecret，否则会抛异常
     * @param code
     * @return
     */
    public  String getOpenId(String code){
        log.debug("根据code请求openid:{}",code);
        if(StringUtils.hasText(appId)==false){
            throw new MissingPropertiesException("缺少appId的配置信息，请通过xihuanjun.miniapp.app-id进行设置");
        }
        if(StringUtils.hasText(appSecret)==false){
            throw new MissingPropertiesException("缺少appSecret的配置信息，请通过xihuanjun.miniapp.app-secret进行设置");
        }
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId+"&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
        JsonNode jsonNode = HttpUtils.sendGet(url);
        String openid = jsonNode.get("openid").toString();
        String resultValue = openid.replace("\"", "");
        log.debug("获取到openid：{}",resultValue);
        return resultValue;
    }

    /**
     * 获取小程序的AT，一个AT可以使用两个小时，存入redis，使用的key是miniapp:access_token，过期（7000秒）后会自动更换
     *
     * @return
     */
    public String getAccessToken() {
        if(StringUtils.hasText(appId)==false){
            throw new MissingPropertiesException("缺少appId的配置信息，请通过xihuanjun.miniapp.app-id进行设置");
        }
        if(StringUtils.hasText(appSecret)==false){
            throw new MissingPropertiesException("缺少appSecret的配置信息，请通过xihuanjun.miniapp.app-secret进行设置");
        }
        //先尝试去redis里读
        String access_token = redisTemplate.opsForValue().get("miniapp:access_token");
        if (StringUtils.hasText(access_token) == false) {
            log.debug("redis里at已过期，开始网络获取");
            String url = MessageFormat.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}",
                    appId, appSecret);
            JsonNode jsonNode = HttpUtils.sendGet(url);
            try {
                access_token =jsonNode.get("access_token").toString();
                log.debug("网络获取到的at:"+access_token);
                //存入redis
                redisTemplate.opsForValue().set("miniapp:access_token", access_token, 7000, TimeUnit.SECONDS);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            log.debug("redis里的at:"+access_token);
        }
        return access_token;
    }

    /**
     * 给微信用户发送一条通知
     *
     * @param openId
     * @param tempId 模板编号
     * @param data   数据
     * @return
     */
    public boolean sendMessage(String openId, String tempId, String data) {
        log.debug("发送消息：openID:{},tempID:{},data:{}",openId,tempId,data);
        if(appState==null){
            throw new MissingPropertiesException("缺少appState的配置信息，请通过xihuanjun.miniapp.app-state进行设置");
        }
        String at = getAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + at;
        Map<String, Object> map = new HashMap<>();
        map.put("template_id", tempId);
        map.put("touser", openId);
        map.put("data", JSONUtils.stringToMap(data));
        map.put("miniprogram_state", appState.toString().toLowerCase());//developer为开发版；trial为体验版；formal为正式版；
        map.put("lang", "zh_CN");
        String result = HttpUtils.sendPost(url, JSONUtils.jsonToString(map));
        log.debug("发送结果：{}",result);
        Map resultMap = JSONUtils.stringToMap(result);
        int errcode = Integer.parseInt(resultMap.get("errcode").toString());
        if(errcode==0){
            return true;
        }
        JsonResult errmsg = new JsonResult().code(errcode).msg(resultMap.get("errmsg").toString());
        throw new MiniAppException(JSONUtils.jsonToString(errmsg));
    }
}
